import cProfile
import pstats
from pstats import SortKey
import io
from typing import Callable, Any
import inspect
import time

profiler = cProfile.Profile()
profile_funcs: list[str] = []
profile_cumtimes: list[float] = []

def get_function_name(func: Callable) -> str:
    return inspect.getmembers(func, predicate=inspect.isfunction)[0][0]

def profile_decorator(func: Callable) -> Any:
    def wrapper(*args, **kwargs):
        global profiler, profile_funcs
        profiler.enable()
        start_time = time.time()

        result = func(*args, **kwargs)

        end_time = time.time()
        profiler.disable()
        profile_funcs.append(func.__name__)
        profile_cumtimes.append(end_time - start_time)
        return result
    return wrapper

def profile_print():
    global profiler, profile_funcs

    stream = io.StringIO()
    stats = pstats.Stats(profiler, stream=stream)
    stats.strip_dirs()
    stats.sort_stats(SortKey.CUMULATIVE)

    head = '{:>4}  {:>10}  {:>10}  {:>10}  {:>10}   {:<15}'.format(
        '', 'ncalls', 'tottime', 'percall', 'cumtime', 'function_name'
    )
    n = len(head) + 15
    print(head)
    print('-' * n)

    # 打印分析结果
    i = 0
    for func, info in stats.get_stats_profile().func_profiles.items():
        if func not in profile_funcs:
            continue
        ncall = info.ncalls
        tottime = info.tottime
        percall = info.percall_tottime
        cumtime = profile_cumtimes[i]
        i += 1
        print('{:>4}  {:>10}  {:>10.4f}  {:>10.4f}  {:>10.4f}   {:<15}'.format(
            i, ncall, tottime, percall, cumtime, func
        ))
    print('-' * n)